// META: title=test WebNN API element-wise lesserOrEqual operation
// META: global=window,dedicatedworker
// META: variant=?cpu
// META: variant=?gpu
// META: variant=?npu
// META: script=../resources/utils.js
// META: timeout=long

'use strict';

// https://www.w3.org/TR/webnn/#api-mlgraphbuilder-logical
// Compare if the values of the first input tensor is lesser or equal,
// element-wise.
//
// MLOperand lesserOrEqual(MLOperand a, MLOperand b);


const getLesserOrEqualPrecisionTolerance = (graphResources) => {
  const toleranceValueDict = {uint8: 0};
  const expectedDataType =
      getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
  return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
};

const lesserOrEqualTests = [
  {
    'name': 'lesserOrEqual float32 0D scalar',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [-6.978766441345215],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [6.613064765930176],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output':
            {'data': [1], 'descriptor': {'dimensions': [], 'dataType': 'uint8'}}
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 1D constant tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'},
          'constant': true
        },
        'inputB': {
          'data': [
            5.498841285705566,    1.766266107559204,   -2.815573215484619,
            -6.048312187194824,   9.497536659240723,   -2.101574659347534,
            -4.079037189483643,   5.314040184020996,   0.03871455416083336,
            -0.30728286504745483, 4.97542667388916,    3.462601661682129,
            8.605685234069824,    1.5140480995178223,  2.0090959072113037,
            -0.3105867803096771,  -4.244836330413818,  -3.5506834983825684,
            -2.5953285694122314,  -4.9998064041137695, 3.118950605392456,
            9.705141067504883,    9.54673957824707,    -6.189505577087402
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'},
          'constant': true
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 1D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            5.498841285705566,    1.766266107559204,   -2.815573215484619,
            -6.048312187194824,   9.497536659240723,   -2.101574659347534,
            -4.079037189483643,   5.314040184020996,   0.03871455416083336,
            -0.30728286504745483, 4.97542667388916,    3.462601661682129,
            8.605685234069824,    1.5140480995178223,  2.0090959072113037,
            -0.3105867803096771,  -4.244836330413818,  -3.5506834983825684,
            -2.5953285694122314,  -4.9998064041137695, 3.118950605392456,
            9.705141067504883,    9.54673957824707,    -6.189505577087402
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 2D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            5.498841285705566,    1.766266107559204,   -2.815573215484619,
            -6.048312187194824,   9.497536659240723,   -2.101574659347534,
            -4.079037189483643,   5.314040184020996,   0.03871455416083336,
            -0.30728286504745483, 4.97542667388916,    3.462601661682129,
            8.605685234069824,    1.5140480995178223,  2.0090959072113037,
            -0.3105867803096771,  -4.244836330413818,  -3.5506834983825684,
            -2.5953285694122314,  -4.9998064041137695, 3.118950605392456,
            9.705141067504883,    9.54673957824707,    -6.189505577087402
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 3D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            5.498841285705566,    1.766266107559204,   -2.815573215484619,
            -6.048312187194824,   9.497536659240723,   -2.101574659347534,
            -4.079037189483643,   5.314040184020996,   0.03871455416083336,
            -0.30728286504745483, 4.97542667388916,    3.462601661682129,
            8.605685234069824,    1.5140480995178223,  2.0090959072113037,
            -0.3105867803096771,  -4.244836330413818,  -3.5506834983825684,
            -2.5953285694122314,  -4.9998064041137695, 3.118950605392456,
            9.705141067504883,    9.54673957824707,    -6.189505577087402
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 4D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            5.498841285705566,    1.766266107559204,   -2.815573215484619,
            -6.048312187194824,   9.497536659240723,   -2.101574659347534,
            -4.079037189483643,   5.314040184020996,   0.03871455416083336,
            -0.30728286504745483, 4.97542667388916,    3.462601661682129,
            8.605685234069824,    1.5140480995178223,  2.0090959072113037,
            -0.3105867803096771,  -4.244836330413818,  -3.5506834983825684,
            -2.5953285694122314,  -4.9998064041137695, 3.118950605392456,
            9.705141067504883,    9.54673957824707,    -6.189505577087402
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 5D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            5.498841285705566,    1.766266107559204,   -2.815573215484619,
            -6.048312187194824,   9.497536659240723,   -2.101574659347534,
            -4.079037189483643,   5.314040184020996,   0.03871455416083336,
            -0.30728286504745483, 4.97542667388916,    3.462601661682129,
            8.605685234069824,    1.5140480995178223,  2.0090959072113037,
            -0.3105867803096771,  -4.244836330413818,  -3.5506834983825684,
            -2.5953285694122314,  -4.9998064041137695, 3.118950605392456,
            9.705141067504883,    9.54673957824707,    -6.189505577087402
          ],
          'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0
          ],
          'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 broadcast 0D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [4.840610980987549],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 broadcast 1D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [4.840610980987549],
          'descriptor': {'dimensions': [1], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 broadcast 2D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -8.499547004699707, -8.321310043334961, -7.182070732116699,
            3.418306350708008, 5.389469146728516, 6.904313087463379
          ],
          'descriptor': {'dimensions': [2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1,
            0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 broadcast 3D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            4.195140838623047, 7.8286590576171875, 6.6902031898498535,
            0.9247010350227356
          ],
          'descriptor': {'dimensions': [2, 2, 1], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'uint8'}
        }
      }
    }
  },
  {
    'name': 'lesserOrEqual float32 broadcast 4D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [4.840610980987549],
          'descriptor': {'dimensions': [1, 1, 1, 1], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -8.284008979797363, -3.219264507293701,  -6.543179988861084,
            -0.540285050868988, -5.413843631744385,  5.583743095397949,
            1.50178062915802,   6.5922441482543945,  -9.92548656463623,
            -7.134799957275391, -4.915772914886475,  -9.137166976928711,
            9.40368366241455,   -9.831502914428711,  -2.0123181343078613,
            -6.597689628601074, -8.26932144165039,   8.281030654907227,
            1.64528226852417,   -1.4862726926803589, -4.998753547668457,
            -0.920993447303772, -9.434256553649902,  9.813238143920898
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'lesserOrEqual',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'uint8'}
        }
      }
    }
  }
];

if (navigator.ml) {
  lesserOrEqualTests.forEach((test) => {
    webnn_conformance_test(
        buildGraphAndCompute, getLesserOrEqualPrecisionTolerance, test);
  });
} else {
  test(() => assert_implements(navigator.ml, 'missing navigator.ml'));
}
